package com.minivision.sdktestdemo.service;


import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.media.AudioManager;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Process;
import android.support.annotation.Nullable;

import com.minivision.sdktestdemo.bean.MusicBean;
import com.minivision.sdktestdemo.controler.service.MusicServiceControler;
import com.minivision.sdktestdemo.event.DataModificationEvent;
import com.minivision.sdktestdemo.event.PlayMusicEvent;
import com.minivision.sdktestdemo.model.MusicProvider;
import com.minivision.sdktestdemo.model.Provider;
import com.minivision.sdktestdemo.notification.MusicControlNotification;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.net.HttpURLConnection;
import java.util.List;

import okhttp3.OkHttpClient;
import rx.Observable;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

public class MusicService extends Service {
    public static final int LOOP = 1;
    public static final int RAND = 2;
    public static final int ALL = 3;
    public static final String MUSIC_SAVE_URI = ".music_loading";
    public static final int UPDATE_PROGRESS = 1;

    private MusicServiceControler mMusicPlayControler;
    private Handler mHandler;
    private boolean mIsInit;
    public boolean mIsStopUpdated;
    private MusicControlNotification mNotification;

    public MusicService() {
        mIsStopUpdated = false;
        EventBus.getDefault().register(this);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        int status = intent != null ? intent.getIntExtra(MusicControlNotification.STATUS, MusicControlNotification.ACTION_INIT) : MusicControlNotification.ACTION_INIT;
        switch (status) {
            case MusicControlNotification.ACTION_PLAY_CHANGE:
                status = mMusicPlayControler.getPlayingEvent().mStatus == PlayMusicEvent.PLAY ? PlayMusicEvent.PAUSE : PlayMusicEvent.PLAY;
                break;
            case MusicControlNotification.ACTION_CLOSE:
                closeMusicService();
                return super.onStartCommand(intent, flags, startId);
            case MusicControlNotification.ACTION_PREV:
                status = PlayMusicEvent.PREV;
                break;
            case MusicControlNotification.ACTION_NEXT:
                status = PlayMusicEvent.NEXT;
                break;
            case MusicControlNotification.ACTION_INIT:
            default:
                return super.onStartCommand(intent, flags, startId);
        }
        PlayMusicEvent event = mMusicPlayControler.getPlayingEvent();
        event.mStatus = status;
        EventBus.getDefault().post(event);
        return Service.START_REDELIVER_INTENT;
    }

    private void closeMusicService() {
        mNotification.close();
        mMusicPlayControler.stop();
        stopSelf();
    }

    @Override
    public void onCreate() {
        super.onCreate();
        //创建控制器
        mMusicPlayControler = new MusicServiceControler(MusicProvider.getInstance(this));
        mNotification = new MusicControlNotification(this);
    }

    public void initEvent() {
        if (!mIsInit) {
            Observable.just(mMusicPlayControler)
                    .map(new Func1<MusicServiceControler, PlayMusicEvent>() {
                        @Override
                        public PlayMusicEvent call(MusicServiceControler musicServiceControler) {
                            musicServiceControler.load(getSharedPreferences(MUSIC_SAVE_URI, MODE_APPEND));
                            musicServiceControler.update();
                            musicServiceControler.generateOrder(musicServiceControler.getPlayingEvent().mOrder);
                            int index = musicServiceControler.indexOf(musicServiceControler.getPlayingEvent().mUri);
                            musicServiceControler.getPlayingEvent().mAlbumUri = index != -1 ? musicServiceControler.getPlayMusicEvent(index).mAlbumUri : null;
                            musicServiceControler.getPlayingEvent().mUri = index != -1 ? musicServiceControler.getPlayingEvent().mUri : "";
                            return mMusicPlayControler.getPlayingEvent();
                        }
                    })
                    .subscribeOn(Schedulers.newThread())
                    .subscribe(new Action1<PlayMusicEvent>() {
                        @Override
                        public void call(PlayMusicEvent event) {
                            EventBus.getDefault().post(event);
                        }
                    });
            mIsInit = true;
        }
    }

    @Override
    public void onDestroy() {
        EventBus.getDefault().unregister(this);
        release();
        super.onDestroy();
    }

    public void release() {
        mMusicPlayControler.stop();
        mMusicPlayControler.save(getSharedPreferences(MUSIC_SAVE_URI, MODE_APPEND));
        mMusicPlayControler.release();
        mMusicPlayControler = null;
        mHandler = null;
        mNotification.close();
        mNotification = null;
        Provider.release();
    }

    public class LocalBinder extends Binder {
        public MusicService getService() {

            return MusicService.this;
        }


    }

    public void setHandler(Handler handler) {
        mHandler = handler;
    }

    public void startUpdate() {
        mIsStopUpdated = false;
        mHandler.post(update);
    }

    public void stopUpdate() {
        mIsStopUpdated = true;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new LocalBinder();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        mHandler = null;
        mIsStopUpdated = true;
        return super.onUnbind(intent);
    }

    private final AudioManager.OnAudioFocusChangeListener mChangeListener = new AudioManager.OnAudioFocusChangeListener() {
        @Override
        public void onAudioFocusChange(int focusChange) {
            if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {

            } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
                mMusicPlayControler.getPlayingEvent().mStatus = PlayMusicEvent.PAUSE;
                EventBus.getDefault().post(mMusicPlayControler.getPlayingEvent());
            } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {

            }
        }
    };

    public boolean isAudioFocused() {
        AudioManager manager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        int result = manager.requestAudioFocus(mChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
        if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
            //
//            manager.registerAudioDeviceCallback();
            return true;
        }
        return false;
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void play(PlayMusicEvent event) {
        switch (event.mStatus) {
            case PlayMusicEvent.PLAY:
//                if (isAudioFocused()) {
                    mMusicPlayControler.play(event);
                    LockService.sIsShow = true;
                    mNotification.updateNotification(event.mName, event.mSubName, event.mAlbumUri, event.mStatus, false);
//                }
                break;
            case PlayMusicEvent.PAUSE:
                mMusicPlayControler.pause();
                LockService.sIsShow = false;
                mNotification.updateNotification(event.mName, event.mSubName, event.mAlbumUri, event.mStatus, false);
                break;
            case PlayMusicEvent.NEXT:
                mMusicPlayControler.playNext(event);
                break;
            case PlayMusicEvent.PREV:
                mMusicPlayControler.playPrev(event);
                break;
            case PlayMusicEvent.SEEK:
                mMusicPlayControler.seekTo(event.mCurPos);
                break;
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onModify(DataModificationEvent event) {
        switch (event.mAction) {
            case DataModificationEvent.ACTION_DELETE:
                if (event.mBeans.size() == 1) {
                    mMusicPlayControler.remove(event.mBeans.get(0));
                } else {
                    mMusicPlayControler.remove(event.mBeans);
                }
                break;
            case DataModificationEvent.ACTION_GROUP_PLAY:
                mMusicPlayControler.play(event.mBeans);
                break;
            case DataModificationEvent.ACTION_LIST_CLEAR:
                mNotification.close();
                mMusicPlayControler.stop();
                break;
        }
    }

    private Runnable update = new Runnable() {
        @Override
        public void run() {
            if (mHandler != null) {
                Message msg = mHandler.obtainMessage(UPDATE_PROGRESS);
                if (mMusicPlayControler.getPlayingEvent() != null
                        && mMusicPlayControler.getPlayingEvent().mStatus == PlayMusicEvent.PLAY
                        && !mIsStopUpdated) {
                    msg.arg1 = getProgress();
                    msg.arg2 = getMaxProgress();
                    mHandler.sendMessage(msg);
                    mHandler.postDelayed(update, 400);
                }
            }
        }
    };

    public void changeOrder() {
        mMusicPlayControler.changeOrder(mMusicPlayControler.getPlayingEvent().mOrder);
    }

    public List<MusicBean> getPlayList() {
        return mMusicPlayControler.getPlayList();
    }

    public PlayMusicEvent getPlayingMusic() {
        return mMusicPlayControler.getPlayingEvent();
    }

    public int getMaxProgress() {
        return mMusicPlayControler.getMaxProgress();
    }

    public int getProgress() {
        return mMusicPlayControler.getProgress();
    }
}
